# -*- coding: utf8 -*-
##############################################################
#             Copyright (C), 2009-2013, ali
#
# FileName:   SDTReport.py
# Author:     yixun.zengyx
# Version:    0.1
#
# Description:
#   TestInfos and Report
#
#
# Function List:
#
#
# History:
#     <Author/Maintainer>      <Date>      <Modification>
#       yixun.zengyx        2013/03/26    Create this file
#############################################################
import pdb
#pdb.set_trace()
import os,sys
from Lib.SDTCode import *
from Lib.Color import *
from SDTestBase import *
from SDTRunner import *
import random 
import re
from test.test_xml_etree import ExceptionFile
from Lib.IData import *


class TestResult:
    def __init__(self,resultlog=".／log/result.log",detaillog=None,isHtml=True):
        self.__resultlog__ = resultlog
        self.__stdoutlog__ = detaillog
        self._isHtmlTrue = isHtml
        self.stdoutlog = detaillog

        
    def init(self):
        self.__logfileHandle = TestLogger(self.__resultlog__,False)
        if self.__stdoutlog__ is None:
            self.__stdoutlogHandle = TestLogger()
        else:
            self.__stdoutlogHandle = TestLogger(self.__stdoutlog__,self._isHtmlTrue)
        
    def Success(self,log,writefile=False):
        self.__stdoutlogHandle.Success(log)
        if writefile:
            self.__logfileHandle.Success(log)
        
    def Fail(self,log,writefile=False):
        if writefile:
            self.__logfileHandle.Fail(log)
        self.__stdoutlogHandle.Fail(log)
        
    def Skip(self,log,writefile=False):
        if writefile:
            self.__logfileHandle.Skip(log)
        self.__stdoutlogHandle.Skip(log)
        
    def Error(self,log,writefile=False):
        if writefile:
            self.__logfileHandle.Error(log)
        self.__stdoutlogHandle.Error(log)
        
    def Info(self,log,writefile=False):
        self.__stdoutlogHandle.Info(log)
        if writefile:
            self.__logfileHandle.Info(log)
            
    def Input(self,log):
        self.__stdoutlogHandle.Input(log)
        
    def Step(self,log):
        self.__stdoutlogHandle.Step(log)
        
    def Validate(self,log):
        self.__stdoutlogHandle.Validate(log)
        
    def Write(self,content,filename="./log/default.html"):
        open(filename,"w").write(content)
        
    def Close(self):
        self.__logfileHandle.Close()
        if type(self.__stdoutlog__) is str:
            self.__stdoutlogHandle.Close()


class TestClassInfo:
    def __init__(self,ModuleIns,ClassName=None):#
        self.__tclass={}#tclass['classname']=(class instances,tcnamelist)
        self.TestDataSource={}#tclass['classname']=DS
        self.TcListHead = None
        self.TcListTail = None
        self.__classnamelist=[]
        self.CurrentClass = None
        self.moduleins = ModuleIns
        if self.moduleins.CurrentModuleDataFile==None:
            self.datafile = None
        else:
            self.datafile = self.moduleins.CurrentModuleDataFile
            if not os.path.isfile(self.datafile):
                self.datafile = None
#                 raise ExceptionFile("%s:TestDataFile SourceFile is not exist!"%(self.datafile))
        if ClassName==None:
            filename = self.moduleins.__file__
            filename=re.sub(".pyc",".py",filename)
            if not os.path.isfile(filename):
                raise ExceptionFile("%s:TestCase SourceFile is not exist!"%(filename))
            self.__classnamelist = self.__classnamelist=HandleData.parserClass(filename)
        else:
            self.__classnamelist.append(ClassName)

        
    def next(self):
        if type(self.__classnamelist) is not list:
            self.CurrentClass = None
            return TcClassListIsError
        if self.__classnamelist==[]:
            self.CurrentClass = None
            return TcClassListIsNull
        self.CurrentClass = self.__classnamelist.pop(0)
        if self.__addins(self.CurrentClass):
            return GetTcClassIsSuccess
        else:
            return GetTcClassIsFail
        
    def getdata(self,classname):
        if self.datafile==None:
            return None
        if os.path.isfile(self.datafile):
            return ParsConf.getclassdata(self.datafile,classname)
        else:
            return None
            
        
    def getins(self,name):
        if type(name) is not str:
            return None
        if (name.lstrip(' ')==''):
            return None
        tname = name.lstrip(' ').rstrip(' ')
        if self.__tclass.has_key(tname):
            return self.__tclass[tname]
        else:
            return None
        
    def getcurrent(self):
        if self.__tclass.has_key(self.CurrentClass):
            return self.__tclass[self.CurrentClass]
        else:
            return None
        
    def update(self,tclist=None):
        if tclist==[] or tclist==None:
            self.__addins(self.CurrentClass,True)
            return
        if type(tclist) is not list:
            return
        tmplist = []
        ins,oldlist = self.__tclass[self.CurrentClass]
        for tcname in tclist:
            if tcname in oldlist:
                tmplist.append(tcname)
        if type(tmplist) is list:
            self.__tclass[self.CurrentClass] = ins,tmplist
            tclistlen = len(tmplist)
            if tclistlen>0:
                self.TcListHead = tmplist[0]
                self.TcListTail = tmplist[tclistlen-1]
        
    def __addins(self,name,isupdate=False):
        if type(name) is not str:
            return False
        if (name.lstrip(' ')==''):
            return False
        tname = name.lstrip(' ').rstrip(' ')
        if self.__tclass.has_key(tname):
            if isupdate==False:
                return True
        self.__tclass[tname]=Loader.getClassInstance(tname)
        self.TestDataSource[tname] = self.getdata(tname)
        self.TcListHead = None
        self.TcListTail = None
        if type(self.__tclass[tname][1]) is list:
            tclistlen = len(self.__tclass[tname][1])
            if tclistlen>0:
                self.TcListHead = self.__tclass[tname][1][0]
                self.TcListTail = self.__tclass[tname][1][tclistlen-1]
            return True
        else:
            return False
        
            
    def __delins(self,name):
        if type(name) is not str:
            return False
        if (name.lstrip(' ')==''):
            return False
        tname = name.lstrip(' ').rstrip(' ')
        if self.__tclass.has_key(tname):
            del self.__tclass[tname]
        return True

class ImportModuleFail(Exception):
    pass

class ParsConf:
    @staticmethod
    def getpackage(config,modulename):
        pakagelist = []
        xml = DataImport(config)
        r = xml.get()
        if not r.has_key("module"):
            return pakagelist
        if type(r.module) is list:
            for modulename in r.module:
                if modulename!=None:
                    pakagelist.append({modulename.name:modulename.datafile})
                elif modulename.name==modulename:
                    pakagelist.append({modulename.name:modulename.datafile})
                    break
        else:
            if r.module.has_key("name"):
                if (r.module.name==modulename) or (modulename==None):
                    pakagelist.append({r.module.name:r.module.datafile})
        return r.path,pakagelist
    
    @staticmethod
    def getclassdata(datafile,classname):
        ds = DataImport(datafile)
        return ds.get(classname)
            

class ModuleInfo:
    def __init__(self,configfile=None,ModuleName=None):#TcMoudle['MoudleName']=TcInfoObj
        self.Tclass={}#Tclass['moudleName']=(tclassname,TClassInfo())
        self.__ModuleList=[]
        self.path = None
        self.CurrentModule= None
        CurrentModuleDataFile = None
        if type(configfile) is str:
            if not os.path.isfile(configfile):
                raise ExceptionFile("file is not exist!")
            self.path,self.__ModuleList=ParsConf.getpackage(configfile,ModuleName)
            if type(self.__ModuleList) is not list:
                raise ImportModuleFail
            if self.__ModuleList==[]:
                raise ImportModuleFail
        else:
            if type(ModuleName) is str:
                self.__ModuleList.append({ModuleName:None})
        self.ModuleIns = {}
        self.CurrentTcClass = None

    def next(self):
        if type(self.__ModuleList) is not list:
            self.CurrentModule= None
            return PackageListIsNull
        if self.__ModuleList==[]:
            self.CurrentModule= None
            return PackageListIsNull
        tempM = self.__ModuleList.pop(0)
        if type(tempM) is dict:
            self.CurrentModule = tempM.keys()[0]
            CurrentModuleDataFile = tempM[self.CurrentModule]
        self.ModuleIns[self.CurrentModule] = Loader.getobject(self.CurrentModule)
        if (self.path==None) or (CurrentModuleDataFile==None):
            self.ModuleIns[self.CurrentModule].CurrentModuleDataFile = None
        else:
            self.ModuleIns[self.CurrentModule].CurrentModuleDataFile = self.path+CurrentModuleDataFile
        return PackageImportSuccess
    
    def getModuleList(self):
        return self.__ModuleList


class HandleData:

    @staticmethod
    def generateJsonData(accessToken,accessTarget,param):
        data = {"access":{"accessToken":None,"accessTarget":None},"param":None}
        data['access']['accessToken'] = accessToken
        data['access']['accessTarget'] = accessTarget
        data['param'] = param
        return data
    
    @staticmethod
    def getTaobao_csrf_token(Param,content=None):
        if content==None:
            return Param
        strParam = str(Param)
        m = re.findall("<input name=\'_csrf_token\'[A-Za-z0-9\'=\s]*value=\'([A-Za-z0-9]+)\'>",content)
        if len(m)==0:
            return Param
        strParam = strParam.replace("<taobao_csrf_token>", m[0],1)
        paramData = eval(strParam)
        return paramData

    @staticmethod
    def genData(Param):
        if Param==None:
            return Param
        strParam = str(Param)
        m = re.findall("<([a-z];[0-9]+)>",strParam)
        if len(m)==0:
            return Param
        for item in m:
            tStr = HandleData.genDynamicData(item)
            strParam = strParam.replace('<'+item+'>', tStr,1)
            paramData = eval(strParam)
        return paramData

    @staticmethod
    def genDynamicData(s):
        sType = s.split(';')[0]
        num = int(s.split(';')[1])
        if sType=='n':
            str = HandleData.genNum(num)
        elif sType == 's':
            str =  HandleData.genStr(num)
        elif sType == 'e':
            str =  HandleData.genSpecChar(num)
        elif sType == 'r':
            str = HandleData.getRandint(num)
        else:
            str =  ""
        return str
    
    @staticmethod
    def getRandint(n):
        n = int(n)
        if n<=0 : return ""
        nStr = ""
        i = 0
        while i< n:
            s = '9'
            nStr = nStr + s
            i = i + 1
        return str(random.randint(0,int(nStr)))
        
    
    @staticmethod
    def genStr(n):
        n = int(n)
        if n <= 0 : return ""
        str = ""
        i = 0
        while i < n :
            s = random.choice('acbdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
            str = str + s
            i = i + 1
        return str
    @staticmethod
    def genNum(n):
        if n <= 0 : return ""
        str = ""
        i = 0
        while i < n :
            s = random.choice('1234567890')
            str = str + s
            i = i + 1
        return str
    
    @staticmethod
    def genSpecChar(n):
        if n <= 0 : return ""
        str = ""
        i = 0
        while i < n :
            s = random.choice('~!@#$%^&*()_+=-`{}[]?/.>,< |')
            str = str + s
            i = i + 1
        return str
    
    @staticmethod
    def parserPackage(importfile):
        modulelist=[]
        file_object = open(importfile, 'r')
        try:
            for line in file_object:
                m=re.search(r'\s*\#',line)
                if m is not None:
                    continue
                newline = re.sub("[\s\r\n]*",'',line)
                if newline=="":
                    continue
                modulelist.append(newline)
        finally:
            file_object.close()
            return modulelist
        
    @staticmethod
    def parserClass(filename):
        classlist=[]
        file_object = open(filename, 'r')
        try:
            for line in file_object:
                m=re.search(r'\s*[\#\']',line)
                if m is not None:
                    continue
                newline = re.findall("\s*@TestClass\([\s]*([a-zA-Z0-9_\s\=\s\,\"]+)[\s]*\)",line)
                if newline==[]:
                    continue
                newline="".join(newline)
                #有name=的情况
                tclassname=re.findall("[\s]*name*[\s\=\s]*\"([A-Za-z0-9_-]+)*\"[\s]*",newline)
                if tclassname==[]:
                    tclassname=re.findall("[\s]*\"([A-Za-z0-9_-]+)*\"[\s\,]+",newline)
                    if tclassname==[]:
                        tclassname=re.findall("[\s]*\"([A-Za-z0-9_-]+)*\"[\s\,]*",newline)
                        if tclassname==[]:
                            continue
                tclassname="".join(tclassname)
                classlist.append(tclassname)
        finally:
            file_object.close()
            return classlist
        
    @staticmethod
    def parserTestResult(filenamelist):
        fileresult = dict()
        fileresult["fail"] = 0
        fileresult["error"] = 0
        fileresult["success"] = 0
        fileresult['tctotal'] = 0
        fileresult['rate'] = "0.0"
        fileresult["duration"] = ""
        fileresult['state']="测试成功完成"
        stime = 1368108044206566.00
        etime = 0
        for filename in filenamelist:
            file_object = open(filename, 'r')
            filename = filename.decode("UTF8")
            try:
                for line in file_object:
                    infoline = re.findall("\s*\[Info\]",line)
                    failline = re.findall("\s*\[Fail\]",line)
                    errorline = re.findall("\s*\[Error\]",line)
                    successline = re.findall("\s*\[Success\]",line)
                    if len(failline)>0:
                        fileresult["fail"] += 1
                        continue
                    if len(errorline)>0:
                        fileresult["error"] += 1
                        continue
                    if len(successline)>0:
                        fileresult["success"] += 1 
                        continue
                    if len(infoline)>0:
                        start_time = re.findall("\s*\[Info\][\s\-A-Za-z0-9\:\[\]]*start time:<([0-9\.]+)>",line)
                        if len(start_time)>0:
                            for t in start_time:
                                st = float(t)
                                if st<stime:
                                    stime = st
                        end_time = re.findall("\s*\[Info\][\s\-A-Za-z0-9\:\[\]]*terminal time:<([0-9\.]+)>",line)
                        if len(end_time)>0:
                            for t in end_time:
                                et = float(t)
                                if et>etime:
                                    etime = et
            finally:
                file_object.close()
        if fileresult["fail"]>0:
            fileresult['state'] = "测试不通过"
        if fileresult["error"]>0:
            fileresult['state'] = "测试出错"
        tctotal = fileresult["success"] + fileresult["fail"] + fileresult["error"]
        if tctotal>0:
            rate = (float(fileresult["success"]) / tctotal) *100.00
            fileresult['rate'] = "%0.1f"%(rate)
        fileresult['tctotal'] = tctotal
        duration = etime - stime
        if duration<0:
            duration = 0
        if duration>1:
            duration = time.strftime('%d-%H-%M-%S',time.gmtime(duration))
            duration = duration.split("-")
            d = int(duration[0])
            d = d - 1
            h = int(duration[1])
            m = int(duration[2])
            s = int(duration[3])
        else:
            d = 0
            h = 0
            m = 0
            s = 0
            fileresult["duration"] = "1 秒"
        if d>0:
            fileresult["duration"] = fileresult["duration"] + duration[0]+" 天 "
        if h>0:
            fileresult["duration"] = fileresult["duration"] + duration[1]+" 小时 "
        if m>0:
            fileresult["duration"] = fileresult["duration"] + duration[2]+" 分  "
        if s>0:
            fileresult["duration"] = fileresult["duration"] + duration[3]+" 秒"
        return fileresult


